package edu.office.applicationRepository;

import edu.office.entities.*;
import edu.office.tools.EOMessage;
import edu.office.tools.EOMessage1;
import edu.office.tools.StaticFields;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;

import java.util.*;

@Named("leadpointRepositoryA")
@ApplicationScoped
public class LeadpointRepository extends ApplicationCommonRepository<Leadpoint> {

    @Inject
    KnowledgeRepository knowledgeRepository;
    @Inject
    EdgeAmongKnowledgeRepository edgeamongknowledgeRepository;
    @Inject
    SubjectRepository subjectRepository;


    public String myCreate(Leadpoint leadpoint) {
        if (find("KNOWLEDGE_ID", leadpoint.getKNOWLEDGE_ID()).list().isEmpty()) {
            create(leadpoint);
            return EOMessage.getEOMessageENUM(EOMessage1.Succeed);
        } else {
            return EOMessage.getEOMessageENUM(EOMessage1.Already_Exist);
        }

    }

    public List<Leadpoint> getLeadpointList(Student student, Subject subject) {
        return find("select * from Leadpoint where subjectid="
                + subject.getID() + "and student_id=" + student.getId() + " order by id desc").list();
    }


    //如果不满足互斥性质，则删除层次较高的知识点，即属于其他知识点后继的知识点，使其满足；
    public void constraintCheck(Set<Knowledge> knowledgeSet) {
        HashSet<Knowledge> result = new HashSet<>();
        for (Knowledge ki : knowledgeSet) {
            for (Knowledge kj : knowledgeSet) {
                if (!ki.equals(kj)) {
                    if (knowledgeRepository.getSuccessorKnowledges(ki).contains(kj)) {
                        result.add(kj);//kj is in the set of sucessor of ki
                    }
                }
            }
        }
        knowledgeSet.removeAll(result);
    }

    public Leadpoint getNextLeadpoint(Leadpoint leadpoint) {
        Leadpoint result = new Leadpoint();
        result.setSTUDENT_ID(leadpoint.getSTUDENT_ID());
        result.setSUBJECTID(leadpoint.getSUBJECTID());
        Set<Knowledge> temKnowledges = new HashSet<>(knowledgeRepository.getKnowledgesList4LeadingPoint(leadpoint));
        constraintCheck(temKnowledges);
        result.setKNOWLEDGE_ID(knowledgeRepository.getKnowledgeString(temKnowledges));
        return result;
    }

    public boolean isEnd(Leadpoint leadpoint) {
        boolean result = false;
        if (!leadpoint.getKNOWLEDGE_ID().contains(",")) {
            Knowledge temKnowledge = knowledgeRepository.find("ID", Integer.parseInt(leadpoint.getKNOWLEDGE_ID())).firstResult();
            if (knowledgeRepository.getSuccessorKnowledges(temKnowledge).isEmpty()) {
                result = true;
            }
        }
        return result;
    }

    public List<Leadpoint> getKnowledge4Subject(Integer subjectId) {
        return find("STUDENT_ID", subjectId).list();
    }

    //====================================get Leadpoint based on subject========================
    public Leadpoint getLeadpointFront4Subject4Student(Subject subjectId, Student studentId) {
        Leadpoint leadpoint = null;
        //根据学生id和课程id选定知识点前沿id（保存着以前的知识点前沿），取出最大的id号的一行记录
        //一个知识点前沿有多张试卷，取id号最大的testpaper
        //显然下面的执行SQL语句的方法比在内存中查找更节约数据库服务器带宽
        // int maxLeadpoint = 0;
        //下面通过两个SQL语句，避免使用SQL的in中包含另一个表
        String sqlString1 = "select max(id) from LEARNING.LEADPOINT where student_id=" +
                studentId + " and subjectid=" + subjectId;
        List result1 = list(sqlString1);
        String ids = "";
        for (Object id : result1) {
            ids += "," + (Integer) id;
        }
        List<Leadpoint> leadpointsList = new LinkedList<>();
        if (!ids.isEmpty()) {
            String sqlString = "select * from LEARNING.LEADPOINT where id in (" + ids.substring(1) + ")";
            leadpointsList = find(sqlString).list();
        }
        if (!leadpointsList.isEmpty()) {
            leadpoint = leadpointsList.get(0);
            //  maxLeadpoint = leadpointsList.get(0).getId();
        } else {//还未初始化,认为学生还没有测试，所以其分界面应该在起始点后面
            StringBuilder sb = new StringBuilder();
            List<Edgeamongknowledge> startEdgeamongknowledges =
                    edgeamongknowledgeRepository.getEdgeamongknowledges4KnowledgePreOrSucc(
                            subjectRepository.find("ID", subjectId).firstResult().getSTARTKNOWLEDGE(), StaticFields.SUCCESSOR);
            for (Edgeamongknowledge edge : startEdgeamongknowledges) {
                sb.append(",").append(edge.getSUCCESSORNODE());
            }
            String leadpointsKnowledgesIds = sb.toString();
            leadpointsKnowledgesIds = leadpointsKnowledgesIds.contains(",") ? leadpointsKnowledgesIds.substring(1) : "";
            if (!leadpointsKnowledgesIds.isEmpty()) {
                leadpoint = new Leadpoint();
                leadpoint.setKNOWLEDGE_ID(leadpointsKnowledgesIds);
                leadpoint.setSTUDENT_ID(studentId.getId());
                leadpoint.setSUBJECTID(subjectId.getID());
                //因为确定这个知识点前沿还不存在，所以可以直接生成
                persist(leadpoint);
            }
        }

        return leadpoint;
    }


    public void updateLeadPoint(Set<Question> correctQuestionList, Set<Question> wrongQuestionList, Subject subject, Student student) {
        /*
          知识点前沿KNF更新步骤如下：\n 1） 在t时，由对题集得到知识点集合K1；\n 2）
          由K1得到其后继集合Kc，该集合满足互斥性质；如果不满足互斥性质，则删除层次较高的知识点，即属于其他知识点后继的知识点，使其满足； \n
          3） 由错题集得到知识点集合Kw，该集合满足互斥性质；如果不满足，处理方法如上； \n 4） 从K1.removeAll(Kw) 5)
          从KNF(t)中删除K1； \n 6) 合并集合Kc,Kw,得到满足互斥性质的集合K1(t+1)；\n 7）
          KNF(t+1)=KNF(t)\K1∪K1(t+1)\n
         */
        //1）	在t时，由对题集得到知识点集合K1；\n
        Set<Knowledge> k1 = knowledgeRepository.getKnowledges4Question(correctQuestionList);
        //2）	从KNF(t)中删除K1； \n
        //Set<Knowledge> currentKnowledgeSet= new HashSet<>(knowledgeRepository.getKnowledgesList4LeadingPoint(leadpoint));
//        currentKnowledgeSet.removeAll(k1);
        //3）  由K1得到其后继集合Kc，该集合满足互斥性质；
        //放到后面统一处理:如果不满足互斥性质，则删除层次较高的知识点，即属于其他知识点后继的知识点，使其满足；
        Set<Knowledge> kc = new HashSet<>();
//        for (Knowledge knowledge : currentKnowledgeSet) {
//            kc.addAll(knowledgeRepository.getSuccessorKnowledges(knowledge));
//        }
        //4）  由错题集得到知识点集合Kw，该集合满足互斥性质；如果不满足，处理方法如上；
        Set<Knowledge> kw = knowledgeRepository.getKnowledges4Question(wrongQuestionList);
        //5）  合并集合Kc,Kw,得到满足互斥性质的集合K1(t+1)；
        kc.addAll(kw);
        //如果不满足互斥性质，则删除层次较高的知识点，即属于其他知识点后继的知识点，使其满足
        constraintCheck(kc);
        //生成新的知识点前沿
        String knowledgeIds = "";
        for (Knowledge knowledge : kc) {
            knowledgeIds += knowledge.getID() + ",";
        }
        if (!knowledgeIds.isEmpty()) {
            Leadpoint leadpoint = new Leadpoint();
            leadpoint.setSUBJECTID(subject.getID());
            leadpoint.setSTUDENT_ID(student.getId());
            knowledgeIds = knowledgeIds.substring(1);
            leadpoint.setKNOWLEDGE_ID(knowledgeIds);
            create(leadpoint);
        }
    }

    public List<Knowledge> knowledgeListBySubjectId(Subject subject, Student student) {
        List<Leadpoint> leadpoints;
        Leadpoint lp;
        List<Knowledge> knowledges = new LinkedList<>();
        if (subject != null && subject.getID() != null) {
            leadpoints = find("select * from leadpoint where subjectid=" + subject.getID() + " and student_id=" + student.getId() + " order by id desc").list();
            if (!leadpoints.isEmpty()) {
                lp = leadpoints.get(0);
                knowledges = knowledgeRepository.find("select * from knowledge where id in(" + lp.getKNOWLEDGE_ID() + ")").list();
            }
        }
        return knowledges;
    }


    public String drawCurStudentLeadpoints(Student stu, Subject subject) {
        String result = "digraph {"
                + "node [rx=5 ry=5 labelStyle=\"font: 300 14px 'Helvetica Neue', Helvetica\"] "
                + "edge [labelStyle=\"font: 300 14px 'Helvetica Neue', Helvetica\"]";
        List<Leadpoint> studentLeadpoints = list("STUDENT_ID=1? and SUBJECTID=2?", stu.getId(),subject.getID());
        Map<Leadpoint, List<Knowledge>> knowledges4StuSubjectMap = new HashMap<>();
        for (Leadpoint lp : studentLeadpoints) {
            knowledges4StuSubjectMap.put(lp, knowledgeRepository.getKnowledgeList4Leadpoint(lp));
        }
        StringBuffer nodeStringBuffer = null;
        List<String> nodeList = new ArrayList<>();
        //画节点
        for (Leadpoint lp : studentLeadpoints) {
            nodeStringBuffer = new StringBuffer();
            List<Knowledge> knowledges = knowledges4StuSubjectMap.get(lp);
            for (Knowledge k : knowledges) {
                nodeStringBuffer.append(((Knowledge) k).getNAME())
                        .append(((Knowledge) k).getID())
                        .append(" ");
            }
            nodeList.add(nodeStringBuffer.toString().trim());
            result += "\"" + nodeStringBuffer.toString().trim()
                    + "\" [labelType=\"html\" label=\"<span style='font-size:32px; color:blue; background-color:gray'>" + nodeStringBuffer.toString().trim()
                    + "</span>\"];";
        }

        //画边
        for (int i = 0; i < nodeList.size(); i++) {
            if (i != nodeList.size() - 1) {
                result += "\"" + nodeList.get(i) + "\"->\"" + nodeList.get(i + 1) + "\";";
            }
        }

        return result + "}";
    }


    public String getName4KnowledgeListFromLeadpoint(Leadpoint leadpoint) {
        List<Knowledge> knowledgeList =knowledgeRepository.list("select * from Knowledge where id in("+ leadpoint.getKNOWLEDGE_ID()+")");
        String result = knowledgeRepository.getName4KnowledgeList(knowledgeList);
        return result;
    }

}
